#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>

// // 以下是C++的线程库thread
// // 底层用的是Linux的线程库pthread
// #include <thread>
// void threadrun()
// {
//     while(true)
//     {
//         std::cout << "I am a new thread for C++" << std::endl;
//         sleep(1);
//         break;
//     }
// }
// int main()
// {
//     std::thread t1(threadrun);
//     t1.join();

//     return 0;
// }


// 以下是Linux的线程库pthread，即原生线程库
#include <pthread.h>
#include <sys/syscall.h>

int g_val = 100;
// 函数可以被多个执行流同时执行
// 函数被重入
// 函数重入：同一个函数在未执行完当前调用的情况下，又被再次调用
void show(const std::string& name)
{
    std::cout << name << "say# " << "hello thread" << std::endl;
}
// 两个线程同步进行
void *threadRun(void* args)
{
    const char* name = (const char*)args;
    int cnt = 5;
    pid_t id = syscall(SYS_gettid);

    while(true)
    {
        std::cout << "id: " << id << std::endl;
        printf("%s, pid: %d, g_val: %d, &g_val: 0x%p\n", name, getpid(), g_val, &g_val);
        std::cout << "pthread_self: " << pthread_self() << std::endl;

        // std::cout << "new thread: " << getpid() << std::endl;
        // show("[new thread]");
        sleep(1);

        cnt--;
        if(cnt == 0) break;
    }
    // // pthread_exit:终止调用该函数的线程
    // pthread_exit((void*)100);

    // exit(0);            // 不能用于终止线程
    return (void*)1;

}
int main()
{
    pthread_t tid;
    // 创建线程，除了进程创建时的第一个线程是主线程，其余线程均是新线程
    // 不是系统调用，是线程库方法，所以须引入线程库，即在Linux中运行时带上选项-lpthread
    pthread_create(&tid,nullptr,threadRun,(void*)"Thread 1");

    sleep(1);
    // // pthread_cancel:取消一个执行中的线程
    // pthread_cancel(tid);

    // // 如果pthread_exit用在主线程，会让主线程进入僵尸状态，等待新线程结束后，他才会退出
    // pthread_exit((void*)pthread_self());

    // while(true)
    // {
    //     printf("main thread pid: %d, g_val: %d, &g_val: 0x%p, create new thread tid: %p\n",getpid(),g_val,&g_val,&tid);
    //     // std::cout << "main thread: " << getpid() << std::endl;
    //     // show("[main thread]");
    //     sleep(1);
    //     // 由于数据共享，所以两个线程在进程中看到的内容是一样的
    //     g_val++;
    // }

    sleep(3);
    void *value;
    // pthread_join:等待线程结束
    // 主线程等待时，默认是阻塞等待的
    // 第二个参数是一个输出型参数，即pthread_join调用结束后，出来时带出线程tid的返回值
    // 如果不关心线程tid的返回值则设为nullptr
    pthread_join(tid,&value);

    std::cout << "main thread quit..., ret: " << (long long)value << std::endl;
    sleep(10);

    return 0;
}

// int main()
// {
//     // sizeof(void*):根据计算机的位数变化
//     std::cout << "point size: " << sizeof(void*) << std::endl;
//     // sizeof(void)无参考意义
//     std::cout << "point size: " << sizeof(void) << std::endl;

//     return 0;
// }



// // 向线程的参数和返回值传递对象
// struct Request
// {
//     int _start;
//     int _end;
//     std::string _threadname;

//     Request(int start,int end,std::string threadname)
//         :_start(start)
//         ,_end(end)
//         ,_threadname(threadname)
//     {}
// };
// struct Response
// {
//     int _result;        // 计算结果
//     int _exitcode;      // 计算结果是否可靠

//     Response(int result,int exitcode)
//         :_result(result)
//         ,_exitcode(exitcode)
//     {}
// };
// // 线程的参数和返回值，不仅仅可以用来进行传递一般参数，也可以传递对象
// void *sumCount(void* args)
// {
//     // static_cast:静态类型转换
//     Request* rq = static_cast<Request*>(args);
//     Response* rsp = new Response(0,0);
//     for(int i = rq->_start;i <= rq->_end;i++)
//     {
//         std::cout << rq->_threadname 
//                   << " is running, caling..., " << i;

//         rsp->_result += i;
//         std::cout << " current result: " << rsp->_result << std::endl;

//         usleep(100000);
//     }
//     delete rq;

//     return rsp;
// }
// int main()
// {
//     pthread_t tid;
//     Request *rq = new Request(1,100,"thread 1");
//     pthread_create(&tid,nullptr,sumCount,rq);

//     void *ret;
//     pthread_join(tid, &ret);
//     Response *rsp = static_cast<Response*>(ret);
//     std::cout << "rsp->_result: " << rsp->_result << ", exitcode: " << rsp->_exitcode << std::endl;
//     delete rsp;

//     return 0;
// }


// std::string toHex(pthread_t tid)
// {
//     char hex[64];
//     snprintf(hex, sizeof(hex),"%p",tid);
//     return hex;
// }
// void *threadRoutine(void* args)
// {
//     while(true)
//     {
//         // pthread_self:获取线程自身的ID
//         std::cout << "thread id: " << toHex(pthread_self()) << std::endl;
//         sleep(1);
//     }
// }
// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid,nullptr,threadRoutine,(void*)"thread 1");

//     std::cout << "main thread create thread done, new thread id: " << toHex(tid) << std::endl;
//     pthread_join(tid,nullptr);

//     return 0;
// }

// #define NUM 3
// // 在全局变量前加上__thread，可以让该全局变量变成各个线程的私有变量
// // 这种方式被称为线程的局部存储，只能定义内置类型
// __thread unsigned int number = 0;
// struct threadData
// {
//     std::string tid;
//     std::string threadname;
// };
// std::string toHex(pthread_t tid)
// {
//     char buffer[128];
//     snprintf(buffer,sizeof(buffer),"0x%lx",tid);
    
//     return buffer;
// }
// void InitThreadData(threadData *td,int number)
// {
//     td->threadname = "thread-" + std::to_string(number);     // thread-0
// }
// void *threadRoutine(void *args)
// {
//     // 线程分离：也可以自己分离自己
//     pthread_detach(pthread_self());

//     // int test_i = 0;
//     threadData *td = static_cast<threadData*>(args);
//     int i = 0;
//     std::string tid = toHex(pthread_self());
//     int pid = getpid();

//     while(i < 10)
//     {
//         std::cout << "tid: " << tid << ", pid: " << pid << std::endl;

//         // std::cout << "pid: " << getpid() 
//         //           << ", tid: " << toHex(pthread_self()) 
//         //           << ", threadname: " << td->threadname 
//         //           << ", test_i: " << test_i
//         //           << ", &test_i: " << toHex((pthread_t)&test_i)
//         //           << std::endl;

//         sleep(1);
//         i++;
//         // test_i++;
//     }
//     delete td;

//     return nullptr;
// }
// int main()
// {
//     // 创建多线程
//     std::vector<pthread_t>tids;
//     for(int i = 0;i < NUM;i++)
//     {
//         pthread_t tid;
//         threadData* td = new threadData;
//         InitThreadData(td,i);

//         pthread_create(&tid,nullptr,threadRoutine,td);
//         tids.push_back(tid);
//         // sleep(1);
//     }
//     sleep(1);

//     // for(auto i:tids)
//     // {
//     //     // 新线程被分离后，新线程自动释放资源
//     //     // 由主线程分离线程i
//     //     pthread_detach(i);
//     // }

//     for(int i = 0;i < tids.size();i++)
//     {
//         int n = pthread_join(tids[i],nullptr);
//         printf("n = %d, who = 0x%lx, why: %s\n", n, tids[i], strerror(n));
//     }

//     return 0;
// }